/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import buffer from '@ohos.buffer';

export type Buffer = buffer.Buffer;

export interface BufferClass extends NodeBuffer {
  new(str: string, encoding?: string): Buffer;
  new(size: number): Buffer;
  new(array: Uint8Array): Buffer;
  new(arrayBuffer: ArrayBuffer): Buffer;
  new(array: ReadonlyArray<any>): Buffer;
  new(buffer: Buffer): Buffer;
  prototype: Buffer;
  from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
  from(data: ReadonlyArray<any> | string | Buffer | ArrayBuffer /*| TypedArray*/): Buffer;
  from(str: string, encoding?: string): Buffer;
  isBuffer(obj: any): obj is Buffer;
  isEncoding(encoding: string): boolean;
  // byteLength(string: string | Buffer | DataView | ArrayBuffer, encoding?: string): number;
  concat(list: ReadonlyArray<Buffer>, totalLength?: number): Buffer;
  compare(buf1: Buffer, buf2: Buffer): number;
  alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
  allocUnsafe(size: number): Buffer;
  allocUnsafeSlow(size: number): Buffer;
  poolSize: number;
  // new(str: string, encoding?: string): Buffer;
  //
  // new(size: number): Buffer;
  //
  // new(array: Uint8Array): Buffer;
  //
  // new(arrayBuffer: ArrayBuffer): Buffer;
  //
  // new(array: ReadonlyArray<any>): Buffer;
  //
  // from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
  //
  // from(data: ReadonlyArray<any> | string | Buffer | ArrayBuffer /*| TypedArray*/): Buffer;
  //
  // from(str: string, encoding?: string): Buffer;
  //
  // isBuffer(obj: any): obj is Buffer;
  //
  // isEncoding(encoding: string): boolean;
  //
  // concat(list: ReadonlyArray<Buffer>, totalLength?: number): Buffer;
  //
  // alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
  //
  // allocUnsafe(size: number): Buffer;
  //
  // allocUnsafeSlow(size: number): Buffer;
  //
  // concat(list: ReadonlyArray<Buffer>, totalLength?: number): Buffer;
  // /**
  //  * The same as buf1.compare(buf2).
  //  */
  // compare(buf1: Buffer, buf2: Buffer): number;
  //
  // poolSize: number;
  // prototype: buffer.Buffer;
}

interface NodeBuffer extends Uint8Array {
  write(string: string, offset?: number, length?: number, encoding?: string): number;

  toString(encoding?: string, start?: number, end?: number): string;

  toJSON(): {
    type: 'Buffer',
    data: any[]
  };

  equals(otherBuffer: Buffer): boolean;

  copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;

  writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;

  writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;

  writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;

  writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;

  readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;

  readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;

  readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;

  readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;

  readUInt8(offset: number, noAssert?: boolean): number;

  readUInt16LE(offset: number, noAssert?: boolean): number;

  readUInt16BE(offset: number, noAssert?: boolean): number;

  readUInt32LE(offset: number, noAssert?: boolean): number;

  readUInt32BE(offset: number, noAssert?: boolean): number;

  readInt8(offset: number, noAssert?: boolean): number;

  readInt16LE(offset: number, noAssert?: boolean): number;

  readInt16BE(offset: number, noAssert?: boolean): number;

  readInt32LE(offset: number, noAssert?: boolean): number;

  readInt32BE(offset: number, noAssert?: boolean): number;

  readFloatLE(offset: number, noAssert?: boolean): number;

  readFloatBE(offset: number, noAssert?: boolean): number;

  readDoubleLE(offset: number, noAssert?: boolean): number;

  readDoubleBE(offset: number, noAssert?: boolean): number;

  swap16(): Buffer;

  swap32(): Buffer;

  swap64(): Buffer;

  writeUInt8(value: number, offset: number, noAssert?: boolean): number;

  writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;

  writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;

  writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;

  writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;

  writeInt8(value: number, offset: number, noAssert?: boolean): number;

  writeInt16LE(value: number, offset: number, noAssert?: boolean): number;

  writeInt16BE(value: number, offset: number, noAssert?: boolean): number;

  writeInt32LE(value: number, offset: number, noAssert?: boolean): number;

  writeInt32BE(value: number, offset: number, noAssert?: boolean): number;

  writeFloatLE(value: number, offset: number, noAssert?: boolean): number;

  writeFloatBE(value: number, offset: number, noAssert?: boolean): number;

  writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;

  writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;

  fill(value: any, offset?: number, end?: number): this;

  indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;

  lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;

  entries(): IterableIterator<[number, number]>;

  includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;

  keys(): IterableIterator<number>;

  values(): IterableIterator<number>;
}

interface Uint8Array {
  readonly BYTES_PER_ELEMENT: number;
  readonly buffer: ArrayBufferLike;
  readonly byteLength: number;
  readonly byteOffset: number;

  copyWithin(target: number, start: number, end?: number): this;

  every(predicate: (value: number, index: number, array: Uint8Array) => unknown, thisArg?: any): boolean;

  fill(value: number, start?: number, end?: number): this;

  filter(predicate: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array;

  find(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number | undefined;

  findIndex(predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any): number;

  forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;

  indexOf(searchElement: number, fromIndex?: number): number;

  join(separator?: string): string;

  lastIndexOf(searchElement: number, fromIndex?: number): number;

  readonly length: number;

  map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;

  reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number;

  reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number;

  reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;

  reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number;

  reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number;

  reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;

  reverse(): Uint8Array;

  set(array: ArrayLike<number>, offset?: number): void;

  slice(start?: number, end?: number): Uint8Array;

  some(predicate: (value: number, index: number, array: Uint8Array) => unknown, thisArg?: any): boolean;

  sort(compareFn?: (a: number, b: number) => number): this;

  subarray(begin?: number, end?: number): Uint8Array;

  toLocaleString(): string;

  toString(): string;

  valueOf(): Uint8Array;

  [index: number]: number;
}
